package com.zhanghao.ems.utils;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.PageSize;
import com.lowagie.text.Phrase;
import com.lowagie.text.alignment.VerticalAlignment;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;

public class TablePdf {

  private List<int[]> mergeCells = new ArrayList<>();// 0,0,1,3
  private List<List<DataCell>> dataList = new ArrayList<>();
  private Font font = null;
  private BeforeCreate beforeCreate = null;
  private AfterCreate afterCreate = null;
  private float[] columnDefinitionSize = null;
  private boolean autoMerge = false;

  public TablePdf(List<List<DataCell>> dataList, boolean autoMerge) {
    super();
    this.init(dataList, autoMerge);
  }

  private void init(List<List<DataCell>> dataList, boolean autoMerge) {

    if (dataList == null || dataList.isEmpty()) {
      throw new IllegalArgumentException("dataList参数不能为空");
    }
    this.dataList = dataList;
    this.autoMerge = autoMerge;
    if (this.font == null) {
      BaseFont baseFont;
      try {
        baseFont = BaseFont.createFont("simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        this.font = new Font(baseFont, 10, Font.NORMAL);
      } catch (DocumentException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    if (!this.autoMerge) {// 如果不需要合并单元格，直接返回
      return;
    }

    List<DataCell> firstRow = dataList.get(0);

    // 逐列循环读取，进行合并column
    for (int i = 0; i < firstRow.size(); i++) {

      int startPoint = 0;
      int endPoint = 0;

      // 读取第i列的数据判断是否需要合并单元格row
      for (int j = 0; j < dataList.size(); j++) {
        if (j + 1 >= dataList.size()) {
          if (endPoint - startPoint > 1) {
            int[] merge = { startPoint, i, endPoint, i, };
            this.mergeCells.add(merge);
          }
          break;// 循环到倒数第二行时结束
        }
        List<DataCell> row = dataList.get(j);
        List<DataCell> nextRow = dataList.get(j + 1);
        DataCell dataCell = row.get(i);
        DataCell nextCell = nextRow.get(i);

        // 如果上下紧邻单元的值相等则进行合并单元格。
        if (dataCell.getValue().equals(nextCell.getValue())) {
          endPoint += 1;
        } else {
          /**
           * 如果出现不相等情况
           * 1. 将已经合并的单元格添加到currentMergeCell中
           * 2. 重置指针起始位置
           */
          if (endPoint - startPoint > 0) {
            int[] merge = { startPoint, i, endPoint, i };
            this.mergeCells.add(merge);
          }
          startPoint = j + 1;
          endPoint = j + 1;

        }

      }

    }

  }

  /**
   * @desc 根据数据生成pdf列表,紧邻两行的数据如果相同会自动合并单元格。
   * 
   * @param args no arguments needed
   * @throws IOException
   * @throws DocumentException
   */
  public void createTable(FileOutputStream out) throws DocumentException, IOException {
    System.out.println("TableAttributes");
    // creation of the document with a certain size and certain margins
    Document document = new Document(PageSize.A4.rotate(), 30, 30, 50, 50);

    float width = document.getPageSize().getWidth();

    try {
      // step 2
      PdfWriter.getInstance(document,
          new BufferedOutputStream(out));
      // step 3
      document.open();

      // step 4
      if (columnDefinitionSize == null) {

        // float[] columnDefinitionSize = { 33.33F, 33.33F, 33.33F, 33.33F, 33.33F,
        // 33.33F, 33.33F, 33.33F, 33.33F, 33.33F,
        // 33.33F, 33.33F, 33.33F };
        int size = this.dataList.get(0).size();
        columnDefinitionSize = new float[size];
        float percent = (float) (Math.round(100 / size * 100)) / 100;
        for (int i = 0; i < columnDefinitionSize.length; i++) {
          columnDefinitionSize[i] = percent;
        }

      }

      PdfPTable table = null;
      table = new PdfPTable(columnDefinitionSize);
      table.getDefaultCell().setBorder(1);
      table.setHorizontalAlignment(0);
      table.setTotalWidth(width - 60);
      table.setLockedWidth(true);

      if (beforeCreate != null) {
        beforeCreate.handleTable(document, table);
      }

      for (int i = 0; i < this.dataList.size(); i++) {
        List<DataCell> rows = this.dataList.get(i);
        for (int j = 0; j < rows.size(); j++) {
          DataCell curentCell = rows.get(j);
          this.addCell(table, curentCell, this.font);
        }
        table.completeRow();
      }

      if (afterCreate != null) {
        afterCreate.handleTable(document, table);
      }

      document.add(table);
    } catch (Exception e) {
      e.printStackTrace();
    }
    // we close the document
    document.close();
  }

  private void addCell(PdfPTable table, DataCell dataCell, Font font) {

    int row = dataCell.getRow();
    int column = dataCell.getColumn();

    // 1.循环判断单元格是否在合并区域内，如果在则进行相关处理并返回
    for (int i = 0; i < this.mergeCells.size(); i++) {
      int[] range = this.mergeCells.get(i);
      int startRow = range[0];
      int startColumn = range[1];
      int endRow = range[2];
      int endColumn = range[3];

      // 如果是合并单元格的起始位置，则进行单元格合并操作。
      if (row == startRow && column == startColumn) {
        // 添加合并单元格
        PdfPCell cell = new PdfPCell(new Phrase(dataCell.getValue(), font));
        cell.setRowspan(endRow - startRow + 1);
        cell.setColspan(endColumn - startColumn + 1);
        cell.setVerticalAlignment(VerticalAlignment.CENTER.getId());
        table.addCell(cell);
        return;
      } else if (row <= endRow && row >= startRow && column >= startColumn && column <= endColumn) {
        // 如果dataCell 位于合并单元格区域内，并且不是开始的单元格，则不进行任何操作
        return;
      } else {
        // PdfPCell cell = new PdfPCell(new Phrase(dataCell.getValue(), font));
        // table.addCell(cell);
        // return;
      }
    }

    // 如果上面1循环中，判断当前cell不在合并区域内则添加到table中
    PdfPCell cell = new PdfPCell(new Phrase(dataCell.getValue(), font));
    table.addCell(cell);

  }

  public interface BeforeCreate {
    void handleTable(Document document, PdfPTable table);
  }

  public interface AfterCreate {
    void handleTable(Document document, PdfPTable table);
  }

  public Font getFont() {
    return font;
  }

  public void setFont(Font font) {
    this.font = font;
  }

  public BeforeCreate getBeforeCreate() {
    return beforeCreate;
  }

  public void setBeforeCreate(BeforeCreate beforeCreate) {
    this.beforeCreate = beforeCreate;
  }

  public AfterCreate getAfterCreate() {
    return afterCreate;
  }

  public void setAfterCreate(AfterCreate afterCreate) {
    this.afterCreate = afterCreate;
  }

  public float[] getColumnDefinitionSize() {
    return columnDefinitionSize;
  }

  public void setColumnDefinitionSize(float[] columnDefinitionSize) {
    this.columnDefinitionSize = columnDefinitionSize;
  }

  /*
   * 是否需要合并单元格
   * true 合并单元格
   * false 不合并单元格
   */
  public boolean isAutoMerge() {
    return autoMerge;
  }

  /*
   * 是否需要合并单元格
   * true 合并单元格
   * false 不合并单元格
   */
  public void setAutoMerge(boolean autoMerge) {
    this.autoMerge = autoMerge;
  }

}
